package membership

import (
	"fmt"
	"sync"
	"time"
)

// MemberStatus 表示成员状态
type MemberStatus int

const (
	// MemberStatusUnknown 表示未知状态
	MemberStatusUnknown MemberStatus = iota
	// MemberStatusAlive 表示存活状态
	MemberStatusAlive
	// MemberStatusSuspected 表示可疑状态
	MemberStatusSuspected
	// MemberStatusDead 表示死亡状态
	MemberStatusDead
	// MemberStatusLeft 表示离开状态
	MemberStatusLeft
)

// String 返回成员状态的字符串表示
func (s MemberStatus) String() string {
	switch s {
	case MemberStatusUnknown:
		return "unknown"
	case MemberStatusAlive:
		return "alive"
	case MemberStatusSuspected:
		return "suspected"
	case MemberStatusDead:
		return "dead"
	case MemberStatusLeft:
		return "left"
	default:
		return "unknown"
	}
}

// Member 表示集群成员
type Member struct {
	// ID 是成员的唯一标识符
	ID string
	// Name 是成员的名称
	Name string
	// Address 是成员的地址
	Address string
	// Status 是成员的状态
	Status MemberStatus
	// Tags 是成员的标签
	Tags map[string]string
	// Incarnation 是成员的化身编号，用于解决冲突
	Incarnation uint64
	// LastStatusChange 是最后一次状态变更时间
	LastStatusChange time.Time
	// LastHeartbeat 是最后一次心跳时间
	LastHeartbeat time.Time
}

// NewMember 创建一个新的成员
func NewMember(id, name, address string, tags map[string]string) *Member {
	now := time.Now()
	return &Member{
		ID:               id,
		Name:             name,
		Address:          address,
		Status:           MemberStatusAlive,
		Tags:             tags,
		Incarnation:      1,
		LastStatusChange: now,
		LastHeartbeat:    now,
	}
}

// UpdateStatus 更新成员状态
func (m *Member) UpdateStatus(status MemberStatus, incarnation uint64) bool {
	// 如果新的化身编号小于当前的化身编号，则忽略更新
	if incarnation < m.Incarnation {
		return false
	}

	// 如果新的化身编号等于当前的化身编号，但状态优先级较低，则忽略更新
	if incarnation == m.Incarnation && !isHigherPriority(m.Status, status) {
		return false
	}

	// 更新状态
	m.Status = status
	m.Incarnation = incarnation
	m.LastStatusChange = time.Now()
	return true
}

// UpdateHeartbeat 更新成员心跳
func (m *Member) UpdateHeartbeat() {
	m.LastHeartbeat = time.Now()
}

// IsAlive 检查成员是否存活
func (m *Member) IsAlive() bool {
	return m.Status == MemberStatusAlive
}

// IsSuspected 检查成员是否可疑
func (m *Member) IsSuspected() bool {
	return m.Status == MemberStatusSuspected
}

// IsDead 检查成员是否死亡
func (m *Member) IsDead() bool {
	return m.Status == MemberStatusDead
}

// HasLeft 检查成员是否离开
func (m *Member) HasLeft() bool {
	return m.Status == MemberStatusLeft
}

// String 返回成员的字符串表示
func (m *Member) String() string {
	return fmt.Sprintf("Member{id=%s, name=%s, address=%s, status=%s, incarnation=%d}",
		m.ID, m.Name, m.Address, m.Status.String(), m.Incarnation)
}

// isHigherPriority 检查新状态是否具有更高的优先级
func isHigherPriority(oldStatus, newStatus MemberStatus) bool {
	// 状态优先级：Left > Dead > Suspected > Alive > Unknown
	priorities := map[MemberStatus]int{
		MemberStatusUnknown:   0,
		MemberStatusAlive:     1,
		MemberStatusSuspected: 2,
		MemberStatusDead:      3,
		MemberStatusLeft:      4,
	}
	return priorities[newStatus] > priorities[oldStatus]
}

// MemberList 表示成员列表
type MemberList struct {
	// members 是成员映射表
	members map[string]*Member
	// mu 是互斥锁
	mu sync.RWMutex
}

// NewMemberList 创建一个新的成员列表
func NewMemberList() *MemberList {
	return &MemberList{
		members: make(map[string]*Member),
	}
}

// Add 添加成员
func (ml *MemberList) Add(member *Member) bool {
	ml.mu.Lock()
	defer ml.mu.Unlock()

	// 检查成员是否已存在
	if existing, ok := ml.members[member.ID]; ok {
		// 如果已存在，则更新状态
		return existing.UpdateStatus(member.Status, member.Incarnation)
	}

	// 添加新成员
	ml.members[member.ID] = member
	return true
}

// Remove 移除成员
func (ml *MemberList) Remove(id string) bool {
	ml.mu.Lock()
	defer ml.mu.Unlock()

	if _, ok := ml.members[id]; ok {
		delete(ml.members, id)
		return true
	}
	return false
}

// Get 获取成员
func (ml *MemberList) Get(id string) (*Member, bool) {
	ml.mu.RLock()
	defer ml.mu.RUnlock()

	member, ok := ml.members[id]
	return member, ok
}

// UpdateStatus 更新成员状态
func (ml *MemberList) UpdateStatus(id string, status MemberStatus, incarnation uint64) bool {
	ml.mu.Lock()
	defer ml.mu.Unlock()

	if member, ok := ml.members[id]; ok {
		return member.UpdateStatus(status, incarnation)
	}
	return false
}

// UpdateHeartbeat 更新成员心跳
func (ml *MemberList) UpdateHeartbeat(id string) bool {
	ml.mu.Lock()
	defer ml.mu.Unlock()

	if member, ok := ml.members[id]; ok {
		member.UpdateHeartbeat()
		return true
	}
	return false
}

// GetAll 获取所有成员
func (ml *MemberList) GetAll() []*Member {
	ml.mu.RLock()
	defer ml.mu.RUnlock()

	members := make([]*Member, 0, len(ml.members))
	for _, member := range ml.members {
		members = append(members, member)
	}
	return members
}

// GetByStatus 获取指定状态的成员
func (ml *MemberList) GetByStatus(status MemberStatus) []*Member {
	ml.mu.RLock()
	defer ml.mu.RUnlock()

	members := make([]*Member, 0)
	for _, member := range ml.members {
		if member.Status == status {
			members = append(members, member)
		}
	}
	return members
}

// GetAlive 获取存活的成员
func (ml *MemberList) GetAlive() []*Member {
	return ml.GetByStatus(MemberStatusAlive)
}

// GetSuspected 获取可疑的成员
func (ml *MemberList) GetSuspected() []*Member {
	return ml.GetByStatus(MemberStatusSuspected)
}

// GetDead 获取死亡的成员
func (ml *MemberList) GetDead() []*Member {
	return ml.GetByStatus(MemberStatusDead)
}

// Count 获取成员数量
func (ml *MemberList) Count() int {
	ml.mu.RLock()
	defer ml.mu.RUnlock()
	return len(ml.members)
}

// CountByStatus 获取指定状态的成员数量
func (ml *MemberList) CountByStatus(status MemberStatus) int {
	ml.mu.RLock()
	defer ml.mu.RUnlock()

	count := 0
	for _, member := range ml.members {
		if member.Status == status {
			count++
		}
	}
	return count
}

// String 返回成员列表的字符串表示
func (ml *MemberList) String() string {
	ml.mu.RLock()
	defer ml.mu.RUnlock()

	return fmt.Sprintf("MemberList{count=%d, alive=%d, suspected=%d, dead=%d, left=%d}",
		len(ml.members),
		ml.countByStatusNoLock(MemberStatusAlive),
		ml.countByStatusNoLock(MemberStatusSuspected),
		ml.countByStatusNoLock(MemberStatusDead),
		ml.countByStatusNoLock(MemberStatusLeft))
}

// countByStatusNoLock 获取指定状态的成员数量（无锁版本）
func (ml *MemberList) countByStatusNoLock(status MemberStatus) int {
	count := 0
	for _, member := range ml.members {
		if member.Status == status {
			count++
		}
	}
	return count
}
